home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
disk
/
mt100.zip
/
MT.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-04
|
18KB
|
496 lines
// Move To drive/directory.
// Copyright 1996 Jason Hood
// Started: 14 April, 1996.
// Finished: 4 June.
// Will change drive as well as directory.
// Allows use of slash ("/") as well as backslash ("\").
// Can use multiple dots (eg. treats "..." as "../..").
// Can select previous directory by using "mt;" (or "mt ;" if not so lazy).
// Can also select the directory before the previous directory by using ";;".
// Partial directory names, where searches always start from the root.
// "mt @drives" will construct a directory structure file for drives. "mt @"
// will update the directory structure file for drives already in the file.
// The path is specified via mtmem. The filename is "mtdirs.dat".
// Path and previous directories are stored in memory, allocated by mtmem.
// Acknowledgements: Tim Jones' WASTED.PAS for finding directories.
// You are free to use this code, or a portion thereof, as long as an
// appropriate acknowledgement is made.
// Questions, suggestions and comments to hoodj@topaz.cqu.edu.au.
#include <dir.h>
#include <string.h>
#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
#include <ctype.h>
#include <stdlib.h>
#define version "1.00"
char olddir[MAXDIR], newdir[MAXDIR]; // The current and new directories
char mtdirs[MAXPATH], // Directory structure file
prev[2][MAXDIR]; // Previous directories
char **dirs; // Directories for each drive
int dirnum; // Number of directories on each drive
const int MaxDirs = 1500; // Maximum number of directories/drive
int find(const char* path); // Try and find path
int partdir(int num, char* partial[], char drive); // Find a partial directory
void restore(char drv, const char* rev); // Make a proper pathname
int dirfile(char* drives); // Create directory structure for drives
void finddirs(const char* startdir, const char* parent = "");// Find directories
char* finddirec(struct ffblk &dir, const char* name = ""); // Find dir. name
long index(ofstream& os, char drv); // Index and write drv's directories
int sort(const void* a, const void* b); // How the directories are sorted
int subs(const char* path); // Number of directories in path
void help(); // Display help screen
inline ofstream& wlong(ofstream& os, long num) { // Write a long to a file
os.write((char*)&num, sizeof(long)); // as a binary value
return os;
}
inline ifstream& rlong(ifstream& is, long& num) { // Read a long from a file
is.read((char*)&num, sizeof(long)); // as a binary value
return is;
}
void main(int argc, char* argv[]) {
int bprev = 1, // Update both previous directories
result; // Result from functions
char drive, // Drive specified
*env; // Environment string
unsigned mtmem = 0; // Segment assigned by mtmem.com
if (!(env = getenv("MTMEM")) || *env == '#') {
cout << "You must run \"MTMEM\" first." << endl;
return;
}
// Convert the string into a segment address, assuming it to be valid
for (; *env; env++) mtmem = (mtmem << 4) | (*env & 0x0f);
// It is easier to do this than to muck about with far pointers
movedata(mtmem, 0, _DS, (unsigned)mtdirs, MAXPATH+MAXDIR*2);
olddir[0] = getdisk() + 'A'; // Retrieve the current directory
olddir[1] = ':';
olddir[2] = '\\';
getcurdir(0, olddir+3);
if (argc == 1) { // No parameters
cout << endl
<< " Current directory = " << olddir << endl
<< " Previous directory = " << prev[0] << endl
<< "Before previous directory = " << prev[1] << endl;
return;
}
char *&dir = argv[1], // Alias the first argument
&what = dir[0]; // and its first character
if (what == '?' || dir[1] == '?') { // First or second character help
help();
return;
}
if (what == '@') { // (Re)construct directory structure
result = dirfile(dir+1);
if (result) cout << "Unable to " << (result == 1 ? "create" : "open")
<< " \"" << mtdirs << "\".";
return;
}
if (what == ';') { // Use a previous directory.
bprev = (dir[1] == ';'); // 0 - previous, 1 - before previous
strcpy(newdir, prev[bprev]);
}
else {
if (dir[1] == ':') { // If there is a drive
newdir[0] = drive = toupper(what);
newdir[1] = ':'; // then make the new directory
newdir[2] = 0; // start with it
dir += 2; // and skip past it
}
else newdir[0] = drive = 0;
if (what == '.') { // Parent shortcut
for (int dots = 0; dir[dots] == '.'; dots++); // Count dots
if (dots > 2) // If more than two then replace
for (int j = 0; j < dots-2; j++) { // each dot after two with "../"
strcat(newdir, "../"); // eg. replace first dot of "..." with
dir++; // "../" to get "../.."
}
}
if (argc > 2 || !find(dir)) { // Two parameters or an unfound subdir
result = partdir(argc-1, argv+1, drive); // requires a search
if (result) { // It hasn't worked
switch (result) {
case 1: cout << "Unable to open \"" << mtdirs << "\"."; break;
case 2: cout << drive << ": has not been scanned."; break;
case 3: cout << "No match found.";
}
cout << endl;
return;
}
}
}
if (chdir(newdir) == -1) {
cout << (newdir[1] == ':' ? "Invalid drive or d" : "D")
<< "irectory does not exist." << endl;
return;
}
if (newdir[1] == ':' && newdir[0] != olddir[0])
setdisk(toupper(newdir[0]) - 'A');
// Is finding string length more efficient than copying the whole array?
movedata(_DS, (unsigned)olddir, mtmem, MAXPATH, strlen(olddir)+1);
if (bprev && strcmp(prev[0], olddir))
movedata(_DS, (unsigned)prev[0], mtmem, MAXPATH+MAXDIR, strlen(prev[0])+1);
}
// See if newdir+path exists (newdir may contain the drive). If path ends in
// "*" it will select the first directory that starts with path.
// Return 0 if a search for path is required, otherwise 1.
int find(const char* path) {
int star = (path[strlen(path)-1] == '*'); // Is there a star?
struct ffblk dir;
if (*path == 0) { // Only a drive has been specified
newdir[2] = '.'; // So chdir will work
newdir[3] = 0;
return 1;
}
strcat(newdir, path);
if (!finddirec(dir, newdir) && // The path doesn't exist,
*path != '.' && !star && // isn't a shortcut, doesn't end in star
!strchr(path, '/') && !strchr(path, '\\')) // and is a one name path
return 0; // then need to search for it
if (star) { // Expand the name found
for (int j = strlen(newdir)-2; // Find where the name starts
j >= 0 && // The very beginning or
newdir[j] != '/' && // after a path or
newdir[j] != '\\' &&
newdir[j] != ':'; // after the drive
j--);
strcpy(newdir+j+1, dir.ff_name); // Replace with the actual name
}
return 1; // Found, or not searching
}
// From the partial names try and find a match. If drive is null then search
// all drives in the file. If a match is found return 0, otherwise return 1
// for unable to open the file; 2 for unscanned drive; 3 for no match.
int partdir(int num, char* partial[], char drive) {
ifstream mt(mtdirs, ios::in | ios::binary);
if (!mt) return 1; // Bit of a problem
char drv, let, // Drive we're on, first letter to match
path[MAXDIR], // A possible path
*dir; // Subdirectory to match
long index, next = 0; // File positions
int found; // Pretty much self-explanatory
for (int j = 0; j < num; j++) strupr(partial[j]);
do { // For each drive required to search
mt.seekg(next); // Point to the drive
mt.get(drv); // Get this drive letter
rlong(mt, next); // Pointer to next drive
if (drive) { // Find the drive we want
while (next && drv != drive) {
mt.seekg(next);
mt.get(drv);
rlong(mt, next);
}
if (drv != drive) return 2; // Drive not in file
}
if (isalpha(let = *partial[num-1])) { // First name start with a letter?
mt.seekg((let-'A') * si